interface CarElementVisitor {                       //  interface du visiteur
    void visit(Wheel wheel);
    void visit(Engine engine);
    void visit(Body body);
    void visit(Car car);
}

interface CarElement {                              // Interface pour chacun des elements
    void accept(CarElementVisitor visitor);         // CarElements have to provide accept().
}


class Wheel implements CarElement {                 // Object roue qui est implementé (add void)
    private String name;
    Wheel(String name) {
        this.name = name;
    }
    String getName() {
        return this.name;
    }
    void setName(String name){
        this.name = name;
    }
    
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}
 
class Engine implements CarElement {                //idem avec moteur
    private String nom ;
    public Engine(String nom){
        this.nom = nom ;
    }

    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}
 
class Body implements CarElement {                  //idem avec body
    private String type ;
    public Body(String type){
        this.type = type ;
    }
    public void accept(CarElementVisitor visitor) {
        visitor.visit(this);
    }
}
 
class Car implements CarElement{
    CarElement[] elements;                          //contient tout les element de la voiture(Car en l'occurence) 

    public Car() {
        this.elements = new CarElement[]
          { new Wheel("front left"), new Wheel("front right"),
            new Wheel("back left") , new Wheel("back right"),
            new Body("Epave"), new Engine("Rj45") 
          };
    }
    
    public CarElement[] getElements() {             
        return elements.clone();                    // Return a copy of the array of references.
    }
    
    public void accept(CarElementVisitor visitor) {	        
        for(CarElement element : this.getElements()){
            element.accept(visitor);
        }
        visitor.visit(this);	
    }
 
}
 
class CarElementPrintVisitor implements CarElementVisitor {
    public void visit(Wheel wheel) {      
        System.out.println("Visiting "+ wheel.getName()
                            + " wheel");
    }
    public void visit(Engine engine) {
        System.out.println("Visiting engine");
    }
    public void visit(Body body) {
        System.out.println("Visiting body");
    }
 
    public void visit(Car car) {      
        System.out.println("Visiting car");
    }
}
 
class CarElementDoVisitor implements CarElementVisitor {
    public void visit(Wheel wheel){
        System.out.println("Kicking my "+ wheel.getName() + " wheel");
        wheel.setName("blabla");  
        System.out.println("mon nouveau nom de roue est :" + wheel.getName() );
    }
    public void visit(Engine engine) {
        System.out.println("Starting my engine");
    }
    public void visit(Body body) {
        System.out.println("Moving my body");
    }
    public void visit(Car car) {
        System.out.println("Starting my car");
        
    }
 
}
 
public class VisitorDemo {
    static public void main(String[] args){
        Car car = new Car();
        car.accept(new CarElementPrintVisitor());
        car.accept(new CarElementDoVisitor());
        //car.accept(new 
    }
}

